package com.swak.boot.config.consistency;

import java.util.List;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

import com.swak.Constants;
import com.swak.boot.config.consistency.reliablemsg.ReliablemsgAutoConfiguration;
import com.swak.boot.config.consistency.tcc.TccConsistencyAutoConfiguration;
import com.swak.consistency.ConsistencyLauncher;
import com.swak.consistency.core.aspect.ConsistencyAspect;
import com.swak.consistency.core.aspect.ConsistencyTransAspect;
import com.swak.consistency.core.context.ConsistencyContext;
import com.swak.consistency.core.handle.ConsistencyHandler;
import com.swak.consistency.core.handle.impls.MultiConsistencyHandler;
import com.swak.consistency.core.invoke.JavassistInvoker;
import com.swak.consistency.core.resolve.ContextResolver;
import com.swak.consistency.core.resolve.impls.MultiResolver;
import com.swak.consistency.core.resolve.impls.PropagationResolver;
import com.swak.consistency.core.resolve.impls.ThreadLocalResolver;

/**
 * 基于数据库事务的分布式事务
 * 
 * @author DELL
 */
@Configuration
@ConditionalOnClass({ ConsistencyContext.class })
@ConditionalOnProperty(prefix = Constants.APPLICATION_PREFIX, name = "enableConsistency", matchIfMissing = true)
@Import({ TccConsistencyAutoConfiguration.class, ReliablemsgAutoConfiguration.class })
public class ConsistencyAutoConfiguration {

	@Bean
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public ConsistencyLauncher ConsistencyLauncher(ObjectProvider<List<ContextResolver>> resolversProvider,
			ObjectProvider<List<ConsistencyHandler>> handlersProvider) {

		// 获取配置的处理器
		List<ContextResolver> resolvers = resolversProvider.getIfAvailable();
		List<ConsistencyHandler> handlers = handlersProvider.getIfAvailable();
		if (resolvers == null || resolvers.isEmpty() || handlers == null || handlers.isEmpty()) {
			throw new IllegalArgumentException(
					"must config spring.application.enableTcc = true or spring.application.enableReliableMsg = true");
		}

		// context 处理器
		MultiResolver multiResolver = new PropagationResolver();
		multiResolver.addResolver(new ThreadLocalResolver());
		multiResolver.addResolvers(resolvers);

		// 一致性处理器
		MultiConsistencyHandler multiHandler = new MultiConsistencyHandler();
		multiHandler.addHandlers(handlers);
		return new ConsistencyLauncher(multiHandler, multiResolver);
	}

	/**
	 * 定义一致性处理切面
	 * 
	 * @param resolversProvider
	 * @param handlersProvider
	 * @return
	 */
	@Bean
	public ConsistencyAspect consistencyAspect() {
		return new ConsistencyAspect();
	}

	/**
	 * 定义一致性处理切面
	 * 
	 * @param resolversProvider
	 * @param handlersProvider
	 * @return
	 */
	@Bean
	public ConsistencyTransAspect consistencyTransAspect() {
		return new ConsistencyTransAspect();
	}

	/**
	 * 定义 代码片段的执行方式
	 * 
	 * @return
	 */
	@Bean
	@Primary
	@ConditionalOnMissingBean
	public JavassistInvoker consistencyJavassistInvoker() {
		return new JavassistInvoker();
	}
}